package cn.zhyjohn.paysystem.drud;

import cn.hutool.core.util.IdUtil;
import cn.zhyjohn.paysystem.bean.RefundModel;
import cn.zhyjohn.paysystem.bean.TransfersModel;
import cn.zhyjohn.paysystem.bean.WxPayBean;
import cn.zhyjohn.paysystem.common.HttpUtils;
import cn.zhyjohn.paysystem.common.Response;
import cn.zhyjohn.paysystem.requset.WxRefundParams;
import cn.zhyjohn.paysystem.service.WeChatService;
import com.github.wxpay.sdk.WXPayConstants;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.enums.TradeType;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.model.ShortUrlModel;
import com.ijpay.wxpay.model.UnifiedOrderModel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * @author JOHN
 * @title: WeChatDrud
 * @projectName paysystem
 * @since 2019/8/29
 */
@Slf4j
@Service
public class WeChatDrud implements WeChatService {

    @Autowired
    private WxPayBean wxPayBean;

    private String notify_url = "/wxpay/pay_notify";

    @Override
    public String payNotify(HttpServletRequest request) {
        try {
            BufferedReader reader = request.getReader();
            StringBuilder Response = new StringBuilder();
            while (reader.ready()) {
                Response.append(reader.readLine());
            }
            Map<String, String> params = WxPayKit.xmlToMap(Response.toString());
            String Response_code = params.get("Response_code");
            String attach = params.get("attach");
            String sign = params.get("sign");
            String localSign = WxPayKit.createSign(params, wxPayBean.getPartnerKey(), SignType.MD5);
            if (localSign.equals(sign)) {
                if (WxPayKit.codeIsOk(Response_code)) {
                    // 更新订单信息
                    log.warn("更新订单信息:" + attach);
                    // 发送通知等
                    Map<String, String> xml = new HashMap<String, String>();
                    xml.put("return_code", "SUCCESS");
                    xml.put("return_msg", "OK");
                    return WxPayKit.toXml(xml);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public Response wapPay(HttpServletRequest request, String total_fee, String body) {
        String ipAddr = HttpUtils.getIpAddress();
        Map<String, String> params = UnifiedOrderModel
                .builder()
                .appid(wxPayBean.getAppId())
                .mch_id(wxPayBean.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .body(body)
                .out_trade_no(WxPayKit.generateStr())
                .total_fee(total_fee)
                .spbill_create_ip(ipAddr)
                .notify_url(wxPayBean.getDomain().concat(notify_url))
                .trade_type(TradeType.MWEB.getTradeType())
                .build().createSign(wxPayBean.getPartnerKey(), SignType.MD5);
        // 发送请求
        String xmlResponse = WxPayApi.pushOrder(false, params);
        // 将请求返回的 xml 数据转为 Map，方便后面逻辑获取数据
        Map<String, String> ResponseMap = WxPayKit.xmlToMap(xmlResponse);
        // 判断返回的结果
        String returnCode = ResponseMap.get("return_code");
        if (!WxPayKit.codeIsOk(returnCode)) {
            String returnMsg = ResponseMap.get("return_msg");
            return new Response().failure(returnMsg);
        }
        String ResponseCode = ResponseMap.get("Response_code");
        if (!WxPayKit.codeIsOk(ResponseCode)) {
            String errCodeDes = ResponseMap.get("err_code_des");
            return new Response().failure(errCodeDes);
        }
        return new Response().data(ResponseMap);
    }

    @Override
    public Response webPay(HttpServletRequest request, String openId, String total_fee, String body) {
        String ipAddr = HttpUtils.getIpAddress();
        total_fee = conversion(total_fee);
        Map<String, String> params = UnifiedOrderModel
                .builder()
                .appid(wxPayBean.getAppId())
                .mch_id(wxPayBean.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .body(body)
                .out_trade_no(WxPayKit.generateStr())
                .total_fee(total_fee)
                .spbill_create_ip(ipAddr)
                .notify_url(wxPayBean.getDomain().concat(notify_url))
                .trade_type(TradeType.JSAPI.getTradeType())
                .openid(openId)
                .build()
                .createSign(wxPayBean.getPartnerKey(), SignType.MD5);
        // 发送请求
        String xmlResponse = WxPayApi.pushOrder(false, params);
        // 将请求返回的 xml 数据转为 Map，方便后面逻辑获取数据
        Map<String, String> ResponseMap = WxPayKit.xmlToMap(xmlResponse);
        // 判断返回的结果
        String returnCode = ResponseMap.get("return_code");
        if (!WxPayKit.codeIsOk(returnCode)) {
            String returnMsg = ResponseMap.get("return_msg");
            return new Response().failure(returnMsg);
        }
        String ResponseCode = ResponseMap.get("Response_code");
        if (!WxPayKit.codeIsOk(ResponseCode)) {
            String errCodeDes = ResponseMap.get("err_code_des");
            return  new Response().failure(errCodeDes);
        }

        // 以下字段在return_code 和Response_code都为SUCCESS的时候有返回
        String prepayId = ResponseMap.get("prepay_id");
        // 二次签名，构建公众号唤起支付的参数,这里的签名方式要与上面统一下单请求签名方式保持一致
        Map<String, String> packageParams = WxPayKit.prepayIdCreateSign(prepayId,
                wxPayBean.getAppId(), wxPayBean.getPartnerKey(), SignType.MD5);
        // 将二次签名构建的数据返回给前端并唤起公众号支付
        //String jsonStr = JSON.toJSONString(packageParams);
        return new Response().data( packageParams);
    }

    @Override
    public Response scanCodeOne(String product_id) {
        String nonceStr = Long.toString(System.currentTimeMillis());
        // 生成长链接
        String qrCodeUrl = WxPayKit.bizPayUrl(wxPayBean.getPartnerKey(), wxPayBean.getAppId(), wxPayBean.getMchId(), product_id);
        Map<String, String> params = ShortUrlModel.builder()
                .appid(wxPayBean.getAppId())
                .mch_id(wxPayBean.getMchId())
                .nonce_str(nonceStr)
                .long_url(qrCodeUrl)
                .build()
                .createSign(wxPayBean.getPartnerKey(), SignType.MD5);
        // 转换短链接
        String shortResponse = WxPayApi.toShortUrl(params);
        Map<String, String> shortMap = WxPayKit.xmlToMap(shortResponse);
        String return_code = shortMap.get("return_code");
        if (WxPayKit.codeIsOk(return_code)) {
            String Response_code = shortMap.get("Response_code");
            if (WxPayKit.codeIsOk(Response_code)) {
                qrCodeUrl = shortMap.get("short_url");
            }
        }
        return new Response().data(qrCodeUrl);
    }

    @Override
    public Response wxpay() {
        return null;
    }

    @Override
    public Response scanCodeTwo(HttpServletRequest request, String orderNo, String total_fee) {
        String ipAddr = HttpUtils.getIpAddress();
        //金额转换
        total_fee = conversion(total_fee);
        Map<String, String> params = UnifiedOrderModel
                .builder()
                .appid(wxPayBean.getAppId())
                .mch_id(wxPayBean.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .body("扫码支付")
                .out_trade_no(orderNo)
                .total_fee(total_fee)
                .spbill_create_ip(ipAddr)
                .notify_url(wxPayBean.getDomain().concat(notify_url))
                .trade_type(TradeType.NATIVE.getTradeType())
                .build()
                .createSign(wxPayBean.getPartnerKey(), SignType.MD5);
        // 发送请求
        String xmlResponse = WxPayApi.pushOrder(false, params);
        // 将请求返回的 xml 数据转为 Map，方便后面逻辑获取数据
        Map<String, String> ResponseMap = WxPayKit.xmlToMap(xmlResponse);
        // 判断返回的结果
        String returnCode = ResponseMap.get("return_code");
        if (!WxPayKit.codeIsOk(returnCode)) {
            String returnMsg = ResponseMap.get("return_msg");
            return new Response().failure(returnMsg);
        }
        String ResponseCode = ResponseMap.get("Response_code");
        if (!WxPayKit.codeIsOk(ResponseCode)) {
            String errCodeDes = ResponseMap.get("err_code_des");
            return new Response().failure(errCodeDes);
        }
        return new Response().data(ResponseMap.get("code_url"));
    }

    @Override
    public Response appPay(HttpServletRequest request, String body, String orderNo, String total_fee) {
        String ipAddr = HttpUtils.getIpAddress();
        total_fee = conversion(total_fee);
        Map<String, String> params = UnifiedOrderModel
                .builder()
                .appid(wxPayBean.getAppId())
                .mch_id(wxPayBean.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .body(body)
                .total_fee(total_fee)
                .out_trade_no(orderNo)
                .spbill_create_ip(ipAddr)
                .notify_url(wxPayBean.getDomain().concat(notify_url))
                .trade_type(TradeType.APP.getTradeType())
                .build()
                .createSign(wxPayBean.getPartnerKey(), SignType.MD5);
        // 发送请求
        String xmlResponse = WxPayApi.pushOrder(false, params);
        // 将请求返回的 xml 数据转为 Map，方便后面逻辑获取数据
        Map<String, String> ResponseMap = WxPayKit.xmlToMap(xmlResponse);
        // 判断返回的结果
        String returnCode = ResponseMap.get("return_code");
        if (!WxPayKit.codeIsOk(returnCode)) {
            String returnMsg = ResponseMap.get("return_msg");
            return new Response().failure(returnMsg);
        }
        String ResponseCode = ResponseMap.get("Response_code");
        if (!WxPayKit.codeIsOk(ResponseCode)) {
            String errCodeDes = ResponseMap.get("err_code_des");
            return new Response().failure(errCodeDes);
        }

        // 以下字段在return_code 和Response_code都为SUCCESS的时候有返回
        String prepayId = ResponseMap.get("prepay_id");
        // 二次签名，构建公众号唤起支付的参数,这里的签名方式要与上面统一下单请求签名方式保持一致
        Map<String, String> packageParams = WxPayKit.appPrepayIdCreateSign(wxPayBean.getAppId(), wxPayBean.getMchId(), prepayId
                , wxPayBean.getPartnerKey(), SignType.MD5);
        return new Response().data(packageParams);
    }

    @Override
    public Response jsapi(HttpServletRequest request, String openid, String body, String orderNo, String total_fee) {
        String ipAddr = HttpUtils.getIpAddress();
        total_fee = conversion(total_fee);
        Map<String, String> params = UnifiedOrderModel
                .builder()
                .appid(wxPayBean.getAppId())
                .mch_id(wxPayBean.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .body(body)
                .out_trade_no(orderNo)
                .total_fee(total_fee)
                .spbill_create_ip(ipAddr)
                .notify_url(wxPayBean.getDomain().concat(notify_url))
                .trade_type(TradeType.JSAPI.getTradeType())
                .openid(openid)
                .build()
                .createSign(wxPayBean.getPartnerKey(), SignType.MD5);
        // 发送请求
        String xmlResponse = WxPayApi.pushOrder(false, params);
        // 将请求返回的 xml 数据转为 Map，方便后面逻辑获取数据
        Map<String, String> ResponseMap = WxPayKit.xmlToMap(xmlResponse);
        // 判断返回的结果
        String returnCode = ResponseMap.get("return_code");
        String returnMsg = ResponseMap.get("return_msg");
        if (!WxPayKit.codeIsOk(returnCode)) {
            return new Response().failure(returnMsg);
        }
        String ResponseCode = ResponseMap.get("Response_code");
        if (!WxPayKit.codeIsOk(ResponseCode)) {
            return new Response().failure(returnMsg);
        }

        // 以下字段在return_code 和Response_code都为SUCCESS的时候有返回
        String prepayId = ResponseMap.get("prepay_id");
        // 二次签名，构建公众号唤起支付的参数,这里的签名方式要与上面统一下单请求签名方式保持一致
        Map<String, String> packageParams = WxPayKit.prepayIdCreateSign(prepayId,
                wxPayBean.getAppId(), wxPayBean.getPartnerKey(), SignType.MD5);
        return new Response().data( packageParams);
    }

    @Override
    public Response transfers(HttpServletRequest request, String openId, String body, String amount) {
        String ipAddr = HttpUtils.getIpAddress();
        amount = conversion(amount);
        Map<String, String> params = TransfersModel
                .builder()
                .mch_appid(wxPayBean.getAppId())
                .mchid(wxPayBean.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .desc(body)
                .partner_trade_no(WxPayKit.generateStr())
                .amount(amount)
                .spbill_create_ip(ipAddr)
                .check_name("NO_CHECK")
                .openid(openId)
                .build()
                .createSign(wxPayBean.getPartnerKey(), SignType.MD5);
        // 发送请求
        String xmlResponse = WxPayApi.transfers(params, wxPayBean.getCertPath(), wxPayBean.getMchId());
        // 将请求返回的 xml 数据转为 Map，方便后面逻辑获取数据
        Map<String, String> ResponseMap = WxPayKit.xmlToMap(xmlResponse);
        // 判断返回的结果
        String returnCode = ResponseMap.get("return_code");
        String returnMsg = ResponseMap.get("return_msg");
        if (!WxPayKit.codeIsOk(returnCode)) {
            return new Response().failure(returnMsg);
        }
        String ResponseCode = ResponseMap.get("Response_code");
        if (!WxPayKit.codeIsOk(ResponseCode)) {
            return new Response().failure(returnMsg);
        }
        return new Response().success("提现成功");
    }

    @Override
    public Response refund(WxRefundParams params) {
        String transactionId = params.getTransactionId();
        String out_trade_no = params.getOut_trade_no();
        String refund_fee = params.getRefund_fee();
        String total_fee = params.getTotal_fee();
        if (StringUtils.isNotBlank(transactionId) || StringUtils.isNotBlank(out_trade_no)) {
            total_fee = conversion(total_fee);
            refund_fee = conversion(refund_fee);
            Map<String, String> paramsmap = RefundModel.builder()
                    .appid(wxPayBean.getAppId())
                    .mch_id(wxPayBean.getMchId())
                    .nonce_str(WxPayKit.generateStr())
                    .out_refund_no(IdUtil.fastSimpleUUID())
                    .total_fee(total_fee).refund_fee(refund_fee)
                    .build()
                    .createSign(wxPayBean.getPartnerKey(), SignType.MD5);
            String refund = WxPayApi.orderRefund(false, paramsmap, wxPayBean.getCertPath(), wxPayBean.getMchId());
            return new Response().data(refund);
        }
        return new Response().failure("参数错误");
    }

    /**
     * 金额转换
     *
     * @author JOHN
     * @date 14:51
     **/
    private String conversion(String total_fee) {
        return new BigDecimal(total_fee).multiply(new BigDecimal(100)).intValue() + "";
    }
}
